<?php
/**
 * lsys remote
 * @author     Lonely <shan.liu@msn.com>
 * @copyright  (c) 2017 Lonely <shan.liu@msn.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0
 */
namespace LSYS;
use LSYS\Config\Arr;

class Area{
	/**
	 * 使用表名
	 * @var string
	 */
	public static $table="address";
	
	/**
	 * @var Database
	 */
	protected static $_sdb;
	/**
	 * 设置地址存储数据库
	 */
	public static function db(Database $db=null){
		if ($db==null){
			if (self::$_sdb==null){
				$dbconf=new Arr(array(
						"type"=>\LSYS\Database\PDO\SQLite::class,
						"connection"=>array(
							'dsn'        => 'sqlite:'.__DIR__."/../../assets/area.db",
							'persistent' => FALSE,
						),
				));
				self::$_sdb=Database::instance($dbconf);
			}
			return self::$_sdb;
		}
		self::$_sdb=$db;
	}
	/**
	 *
	 * @var array Area instances
	 */
	protected static $instances = null;
	/**
	 * @param Config $name
	 * @return Area
	 */
	public static function instance(){
		if (! isset ( self::$instances)) {
			
			self::$instances = new Area();
		}
		return self::$instances;
	}
	//数据表格式
	//name      ennamex   acronym  code
	//深圳市    shenzhen   sz        0010102
	//
	/**
	 * @var Database
	 */
	protected $_db;
	public function __construct(){
		$this->_db=self::db();
	}
	/**
	 * 根据字符搜索地址
	 * @param string $key
	 * @param number $offset
	 * @param number $limit
	 * @return array[]
	 */
	public function search($key,$offset=0,$limit=10){
		$db=$this->_db;
		$table=$db->quote_table(self::$table);
		$offset=$offset<=0?0:intval($offset);
		$limit=$limit<=0?10:intval($limit);
		$key=str_replace(array("|","\\","/","'",'"'," ",'~','^','$'), '', $key);
		$key=$db->quote($key."%");
		if (!preg_match("/a-z/i",$key)){
			$where="enname like {$key} or acronym like {$key}";
		}else{
			$where="name like {$key}";
		}
		$sql="select * from {$table} where  {$where} order by LENGTH(code) asc  limit {$limit} offset {$offset}";
		$rows=$db->query(Database::DQL, $sql);
		$out=array();
		foreach ($rows as $v){
			$out[$v['code']]=self::parse($v['code']);
		}
		return $out;
	}
	/**
	 * 连接地址为字符串
	 * @param array $data
	 * @param string $tags
	 * @return boolean|string
	 */
	public function join(array $data,$tags){
		$text=array();
		foreach ($data as $v){
			if (!is_array($v))return false;
			if (!isset($v['name']))continue;
			$text[]=$v['name'];
		}
		return implode($tags, $text);
	}
	/**
	 * 把地区码转为本地码
	 * @param string $area_code
	 * @return string
	 */
	public function areacode_to_code($area_code){
		$db=$this->_db;
		$table=$db->quote_table(self::$table);
		$area_code=$db->quote($area_code);
		$sql="select code from {$table} where areacode={$area_code} limit 1";
		return $db->query(Database::DQL, $sql)->get("code");
	}
	/**
	 * 把本地码转为地区码
	 * @param string $code
	 * @return string
	 */
	public function code_to_areacode($code){
		$db=$this->_db;
		$table=$db->quote_table(self::$table);
		$area_code=$db->quote($code);
		$sql="select areacode  from {$table} where code={$area_code} limit 1";
		return $db->query(Database::DQL, $sql)->get("code");
	}
	/**
	 * 解析一个代码为地址
	 * @param string $code
	 * @param string $is_country 是否包含国家
	 * @return array|array
	 */
	public function parse($code,$join=' ',$is_country=false){
		if (empty($code)) return array();
		$db=$this->_db;
		$table=$db->quote_table(self::$table);
		$len=strlen($code);
		$start=3;
		$where=[];
		while ($start<=$len){
			if (!$is_country&&$start<=3){
				$start+=3;
				continue;
			}
			$where[]=substr($code,0,$start);
			$start+=3;
		}
		if (count($where)==0)return array(null,null);
		$value=$db->quote($where);
		$sql="select * from {$table} where code in {$value} order by code asc";
		$rows=$db->query(Database::DQL, $sql);
		$data=$rows->as_array();
		return array($this->join($data,$join),$data);
	}
	/**
	 * 获取下一级的数量
	 * @param string $like
	 * @return number[]
	 */
	private function _group_code($like){
		$db=$this->_db;
		$table=$db->quote_table(self::$table);
		$c=array();
		$len=strlen($like);
		$plen=3;
		$like.=str_pad('',$plen,"_");
		$qlike=$db->quote($like);
		$sql="select code from {$table} where code like {$qlike}";
		$group=$db->query(Database::DQL, $sql);
		foreach ($group as $v){
			$p=substr($v['code'], 0,$len);
			if (!isset($c[$p]))$c[$p]=1;
			else $c[$p]++;
		}
		return $c;
	}
	/**
	 * 获取某个地址的下级地址
	 * @param string $code
	 * @param string $all 是否获取全部下级[下级的下级]
	 * @return array
	 */
	public function childs($code='156',$all=false){
		$db=$this->_db;
		$table=$db->quote_table(self::$table);
		$out=[];
		if (!$all){
			$plen=3;
			$like=$code.str_pad("",$plen,"_");
			$qlike=$db->quote($like);
			$sql="select * from {$table} where code like {$qlike} order by code asc";
			$rows=$db->query(Database::DQL, $sql);
			if(count($rows)>0){
				$out=$rows->as_array();
				$c=$this->_group_code($like);
				foreach ($out as &$v){
					if(isset($c[$v['code']])){
						$v['childs']=$c[$v['code']];
					}else{
						$plen=6;
						$qlike=$db->quote($v['code'].str_pad("",$plen,'_'));//北京等只有两级,中间一级没数据...
						$sql="select count(*) as total from {$table} where code like {$qlike}";
						$v['childs']=intval($db->query(Database::DQL, $sql)->get('total',0));
					}
				}
			}else{
				//北京等只有两级,中间一级没数据...
				$plen=3;
				$like.=str_pad("",$plen,"_");
				$qlike=$db->quote($like);
				$sql="select * from {$table} where code like {$qlike} order by code asc";
				$rows=$db->query(Database::DQL, $sql);
				$out=$rows->as_array();
				$c=$this->_group_code($like);
				foreach ($out as &$v){
					if(isset($c[$v['code']])){
						$v['childs']=$c[$v['code']];
					}else{
						$v['childs']=0;
					}
				}
			}
			return $out;
		}
		$like="{$code}_%";
		$like=$db->quote($like);
		$sql="select * from {$table} where code like {$like} order by code asc";
		$rows=$db->query(Database::DQL, $sql);
		$l=strlen($code);
		foreach ($rows as $v){
			$code=$v['code'];
			$tlen=strlen($code);
			$tp=3;
			if ($tlen<=$l+$tp){
				$out[$code]=$v;
				continue;
			}
			$_l=$l;
			$len=strlen($code);
			$p=&$out;
			while ($_l<$len){
				$tp=3;
				$_l+=$tp;
				$key=substr($code, 0,$_l);
				if($_l>=$len){//最后一位
					$p[$key]=$v;
				}else{
					if (!isset($p[$key])&&!isset($p[$key]['child'])){
						if ($key==$code){
							$p[$key]=$v;
							$p[$key]['child']=array();
						}
					}
					$p=&$p[$key]['child'];
				}
			}
		}
		return $this->_array_values($out);
	}
	/**
	 * 整理地址数据
	 * @param array $arr
	 * @return array
	 */
	protected function _array_values($arr){
		$t=[];
		$_p=[];
		$_jp=[];
		$p=[];
		foreach ($arr as $k=>$v){
			if (isset($v['child'])&&is_array($v['child'])){
				if (!isset($v['id'])){
					foreach ($v['child'] as $vv){
						$_p[]=$k;
						$p[]=$vv;
					}
					continue;
				}
				$arr[$k]['child']=$this->_array_values($v['child']);
			}
		}
		foreach ($_p as $k){
			unset($arr[$k]);
		}
		foreach ($p as $v){
			$arr[]=$v;
		}
		return array_values($arr);
	}
}
